# -*- coding: utf-8 -*-

from __future__ import with_statement

from datetime import datetime
from werkzeug.urls import url_decode
from urlparse import urlparse

from google.appengine.ext import db
from dicthash.for_testing import TestGoogleDataStore, TestFlask, in_namespace

from lenta.code.backends.working.models import Lenta, Note
from lenta.code.views import get_all_lentas, _browse_lenta, _get_notes_by_tag


class TestBase(TestGoogleDataStore):
    """ """
    def setUp(self):
        """ """
        super(TestBase, self).setUp()
        self.app = TestFlask(__name__)
        self.app.config.update(
            SECRET_KEY = '12345'
        )


class TestGetAllLentas(TestBase):
    """
    Test `lenta.views.get_all_lentas` function.
    """
    def test(self):
        """
        0. set namespace
        1. add several `Lenta` entities.
        2. get them
        """
        with in_namespace('testnamespace'):
            Lenta.new(name="A", desc="A B C").put()
            Lenta.new(name="1", desc="1 2 3").put()
            Lenta.new(name="X", desc="X Y Z").put()
            
        with self.app.test_request_context('/'):
            lentas = get_all_lentas('testnamespace')
            self.assertEqual(len(lentas), 3)
    
    def test_namespace_isolation(self):
        """
        0. set namespace 'X'
        1. add several `Lenta` entities
        2. set namespace 'Y'
        3. add several `Lenta` entities
        4. get then separately
        """
        with in_namespace('X'):
            Lenta.new(name="A", desc="A B C").put()
        with in_namespace('Y'):
            Lenta.new(name="X", desc="X Y Z").put()
        
        with self.app.test_request_context('/'):
            lentasX = get_all_lentas('X')
            self.assertEqual(len(lentasX), 1)
            lentasY = get_all_lentas('Y')
            self.assertEqual(len(lentasY), 1)


class TestBrowseLenta(TestBase):
    """
    Testing `lenta.views._browse_lenta` function.
    """
    def setUp(self):
        """ """
        super(TestBrowseLenta, self).setUp()
        self.dttm_list = [
                    datetime(2012, 1, 31), # 0
                    datetime(2012, 1, 30), #
                    datetime(2012, 1, 29), # 2
                    datetime(2012, 1, 28), #
                    datetime(2012, 1, 27), # 4
                    datetime(2012, 1, 26), #
                    datetime(2012, 1, 25), # 6
                    datetime(2012, 1, 24), #
                    datetime(2012, 1, 23), # 8
                    datetime(2012, 1, 22), #
                    datetime(2012, 1, 21), # 10
                    datetime(2012, 1, 20)  #
        ]
        self.namespace = 'testnamespace'
        with in_namespace(self.namespace):
            self.lenta_key = Lenta.new(name="A", desc="A B C").put()
            note_kwargs = dict(title="Boom!", twit="That's boom",
                               body="Boom-boom-boom.", parent=self.lenta_key)
            db.put([Note.new(pubDate=dttm, **note_kwargs) for dttm in self.dttm_list])
        
    def test_default_dttm(self):
        """
        Test default behavior than dttm is not provided.
        """
        with self.app.test_request_context('/browse?limit=10'):
            res = _browse_lenta(self.namespace, self.lenta_key.id())
            
            notes = [_ for _ in res['notes']]
                    
            self.assertEqual(len(Note.all(namespace=self.namespace).fetch(100)), 12)
            self.assertEqual(len(notes), 10)
            self.assertEqual(url_decode(urlparse(res['next_page_url']).query, cls=dict),
                             {'limit':'10', 'dttm':'2012-01-22-00-00-00'})
            self.assertEqual(res['prev_page_url'], None)
            
    def test_last_page(self):
        """
        Test that for last page res.min_dttm is None.
        """
        with self.app.test_request_context('/browse?limit=10&dttm=2012-01-22-00-00-00'):
            res = _browse_lenta(self.namespace, self.lenta_key.id())
            
            notes = [_ for _ in res['notes']]
        
            self.assertEqual(len(Note.all(namespace=self.namespace).fetch(100)), 12)
            self.assertEqual(len(notes), 2)
            self.assertEqual(res['next_page_url'], None)
            self.assertEqual(url_decode(urlparse(res['prev_page_url']).query, cls=dict),
                             {'limit':'10', 'dttm':'2012-01-21-00-00-00', 'back':''})
            
    def test_back(self):
        """
        Paging backwards.
        """
        with self.app.test_request_context('/browse?limit=10&dttm=2012-01-21-00-00-00&back='):
            res = _browse_lenta(self.namespace, self.lenta_key.id())
            
            notes = [_ for _ in res['notes']]
        
            self.assertEqual(len(Note.all(namespace=self.namespace).fetch(100)), 12)
            self.assertEqual(len(notes), 10)
            self.assertEqual(url_decode(urlparse(res['next_page_url']).query, cls=dict),
                             {'limit':'10', 'dttm':'2012-01-22-00-00-00'})
            self.assertEqual(url_decode(urlparse(res['prev_page_url']).query, cls=dict),
                             {'limit':'10', 'dttm':'2012-01-31-00-00-00', 'back':''}) 


class TestGetNotesByTag(TestBase):
    """
    Testing `lenta.views._get_notes_by_tag` function.
    """
    def setUp(self):
        """ """
        super(TestGetNotesByTag, self).setUp()
        self.dttm_list = [
                    datetime(2012, 1, 31), # 0
                    datetime(2012, 1, 30), #
                    datetime(2012, 1, 29), # 2
                    datetime(2012, 1, 28), #
                    datetime(2012, 1, 27), # 4
                    datetime(2012, 1, 26), #
                    datetime(2012, 1, 25), # 6
                    datetime(2012, 1, 24), #
                    datetime(2012, 1, 23), # 8
                    datetime(2012, 1, 22), #
                    datetime(2012, 1, 21), # 10
                    datetime(2012, 1, 20), #
                    datetime(2012, 1, 19), # 12
                    datetime(2012, 1, 18)  #
        ]
        self.tag_list = [
                    ['firebird'], # 0
                    ['firebird'], #
                    ['firebird'], # 2
                    ['sadko'],    #
                    ['firebird'], # 4
                    ['firebird'], #
                    ['firebird'], # 6
                    ['firebird'], #
                    ['mlada'],    # 8
                    ['firebird'], #
                    ['firebird'], # 10
                    ['firebird'], #
                    ['firebird'], # 12
                    ['firebird'], #
        ]
        
        self.namespace = 'testnamespace'
        with in_namespace(self.namespace):
            self.lenta_key = Lenta.new(name="A", desc="A B C").put()
            
            note_kwargs = dict(title="Boom!", twit="That's boom",
                               body="Boom-boom-boom.", parent=self.lenta_key)
            
            db.put([Note.new(pubDate=dttm, tags=tags, **note_kwargs)
                    for dttm, tags in zip(self.dttm_list, self.tag_list)])
            
    def test_setup(self):
        """ """
        self.assertEqual(len(Note.all(namespace=self.namespace).fetch(100)), 14)
        self.assertEqual(len(Note.all(namespace=self.namespace).filter('tags =', 'firebird').fetch(100)), 12)
        self.assertEqual(len(Note.all(namespace=self.namespace).filter('tags =', 'sadko').fetch(100)), 1)
        self.assertEqual(len(Note.all(namespace=self.namespace).filter('tags =', 'mlada').fetch(100)), 1)     
            
    def test_default_dttm(self):
        """
        Test default behavior than dttm is not provided.
        """
        with self.app.test_request_context('/browse?limit=10'):
            res = _get_notes_by_tag(self.namespace, self.lenta_key.id(), 'firebird')
            
            notes = [_ for _ in res['notes']]
                    
            self.assertEqual(len(notes), 10)
            self.assertEqual(url_decode(urlparse(res['next_page_url']).query, cls=dict),
                             {'limit':'10', 'dttm':'2012-01-20-00-00-00'})
            self.assertEqual(res['prev_page_url'], None)
            
    def test_last_page(self):
        """
        Test that for last page res.min_dttm is None.
        """
        with self.app.test_request_context('/browse?limit=10&dttm=2012-01-24-00-00-00'):
            res = _get_notes_by_tag(self.namespace, self.lenta_key.id(), 'firebird')
            
            notes = [_ for _ in res['notes']]
        
            self.assertEqual(len(notes), 5)
            self.assertEqual(res['next_page_url'], None)
            self.assertEqual(url_decode(urlparse(res['prev_page_url']).query, cls=dict),
                             {'limit':'10', 'dttm':'2012-01-22-00-00-00', 'back':''})   
    def test_back(self):
        """
        Paging backwards.
        """
        with self.app.test_request_context('/browse?limit=10&dttm=2012-01-19-00-00-00&back='):
            res = _get_notes_by_tag(self.namespace, self.lenta_key.id(), 'firebird')
            
            notes = [_ for _ in res['notes']]
        
            self.assertEqual(len(notes), 10)
            self.assertEqual(url_decode(urlparse(res['next_page_url']).query, cls=dict),
                             {'limit':'10', 'dttm':'2012-01-20-00-00-00'})
            self.assertEqual(url_decode(urlparse(res['prev_page_url']).query, cls=dict),
                             {'limit':'10', 'dttm':'2012-01-31-00-00-00', 'back':''}) 